<?php

namespace App\Services\Sms\Drivers;

use App\Services\Sms\SmsSendResult;
use App\Services\Sms\SmsSender;
use Psr\Log\LoggerInterface;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;
use TencentCloud\Sms\V20210111\SmsClient;
use TencentCloud\Sms\V20210111\Models\SendSmsRequest;
use Throwable;

class TencentSmsSender implements SmsSender
{
    public function __construct(
        private readonly array $config,
        private readonly LoggerInterface $logger
    ) {
    }

    public function sendLoginCode(string $phone, string $code, int $ttlMinutes): SmsSendResult
    {
        return $this->sendTemplate('login', $phone, [$code, $ttlMinutes]);
    }

    public function sendDisbursementCode(string $phone, string $code, int $ttlMinutes): SmsSendResult
    {
        return $this->sendTemplate('disbursement', $phone, [$code, $ttlMinutes]);
    }

    /**
     * 实际的发送逻辑。
     */
    protected function sendTemplate(string $templateKey, string $phone, array $params): SmsSendResult
    {
        $templateId = $this->config['templates'][$templateKey] ?? null;
        if (!$templateId) {
            $message = sprintf('Tencent SMS template "%s" not configured.', $templateKey);
            $this->logger->warning($message, [
                'phone' => $phone,
                'params' => $params,
            ]);

            return SmsSendResult::failure($message, [
                'driver' => 'tencent',
                'template' => $templateKey,
            ]);
        }

        $secretId = $this->config['secret_id'] ?? null;
        $secretKey = $this->config['secret_key'] ?? null;
        $sdkAppId = $this->config['sms_sdk_app_id'] ?? null;
        $signName = $this->config['sign_name'] ?? null;

        if (!$secretId || !$secretKey || !$sdkAppId || !$signName) {
            $message = 'Tencent SMS driver misconfigured.';
            $this->logger->error($message, [
                'phone' => $phone,
                'template_key' => $templateKey,
                'missing' => [
                    'secret_id' => (bool) $secretId,
                    'secret_key' => (bool) $secretKey,
                    'sms_sdk_app_id' => (bool) $sdkAppId,
                    'sign_name' => (bool) $signName,
                ],
            ]);

            return SmsSendResult::failure($message, [
                'driver' => 'tencent',
                'template' => $templateKey,
            ]);
        }

        $region = $this->config['region'] ?? 'ap-guangzhou';
        $phoneNumber = strpos($phone, '+') === 0 ? $phone : '+86' . $phone;

        try {
            $credential = new Credential($secretId, $secretKey);

            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint('sms.tencentcloudapi.com');

            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);

            $client = new SmsClient($credential, $region, $clientProfile);

            $request = new SendSmsRequest();
            $request->setSmsSdkAppId($sdkAppId);
            $request->setSignName($signName);
            $request->setTemplateId((string) $templateId);
            $request->setPhoneNumberSet([$phoneNumber]);
            if (!empty($params)) {
                $request->setTemplateParamSet(array_map('strval', $params));
            }

            $response = $client->SendSms($request);
            $statuses = $response->SendStatusSet ?? [];

            if (empty($statuses)) {
                throw new TencentCloudSDKException('EmptyResponse', 'Tencent SMS response does not contain status set.');
            }

            $status = $statuses[0];
            if (($status->Code ?? '') !== 'Ok') {
                $message = $status->Message ?? 'Tencent SMS sending failed.';
                $this->logger->warning('[SMS][TencentDriver] send failed', [
                    'phone' => $phone,
                    'template_key' => $templateKey,
                    'template_id' => $templateId,
                    'params' => $params,
                    'code' => $status->Code ?? null,
                    'message' => $message,
                ]);

                return SmsSendResult::failure($message, [
                    'driver' => 'tencent',
                    'template' => $templateKey,
                    'code' => $status->Code ?? null,
                ]);
            }

            $messageId = $status->SerialNo ?? $response->RequestId ?? null;

            $this->logger->info('[SMS][TencentDriver] send success', [
                'phone' => $phone,
                'template_key' => $templateKey,
                'template_id' => $templateId,
                'params' => $params,
                'serial_no' => $status->SerialNo ?? null,
                'request_id' => $response->RequestId ?? null,
            ]);

            return SmsSendResult::success($messageId, [
                'driver' => 'tencent',
                'template' => $templateKey,
            ]);
        } catch (TencentCloudSDKException|Throwable $exception) {
            $this->logger->error('[SMS][TencentDriver] exception sending sms', [
                'phone' => $phone,
                'template_key' => $templateKey,
                'template_id' => $templateId,
                'params' => $params,
                'region' => $region,
                'exception' => $exception->getMessage(),
            ]);

            return SmsSendResult::failure($exception->getMessage(), [
                'driver' => 'tencent',
                'template' => $templateKey,
            ]);
        }

    }
}
